/**
 * Copyright (C) 2021 - 2031 O-Cubes Co., Ltd.
 */

/****************************************************************
 *  @file    sfud_port.c
 *  @brief   Portable Interface for each platform
 *  @version v1.0
 *  @date    03. Apr. 2023
 *  @author  gonght
 ****************************************************************/
#include <sfud.h>
#include <stdarg.h>
#include "dw_spi.h"
#include "syscounter.h"
#include "device_spi.h"

DEV_SPI_CS_LINE flash_cs = DEV_SPI_CS_LINE_DEF(0);

/**
 * SPI write data then read data
 */
static sfud_err spi_write_read(const sfud_spi *spi, uint8_t *write_buf, size_t write_size, uint8_t *read_buf, size_t read_size)
{
	DEV_SPI_PTR dev_spi_ptr = spi_get_dev(DW_SPI_3_ID);

	dev_spi_ptr->cs = *((DEV_SPI_CS_LINE *)spi->user_data);
	return dw_spi_write_read(dev_spi_ptr, write_buf, write_size, read_buf, read_size);
}

/**
 * QSPI write data then read data
 */
static sfud_err qspi_write_read(const sfud_spi *spi, uint8_t *write_buf, size_t write_size, uint8_t *read_buf, size_t read_size)
{
	DEV_SPI_PTR dev_spi_ptr = spi_get_dev(DW_SPI_3_ID);

	dev_spi_ptr->cs = *((DEV_SPI_CS_LINE *)spi->user_data);
	return dw_qspi_write_read(dev_spi_ptr, write_buf, write_size, read_buf, read_size);
}

static void spi_lock(const sfud_spi *spi)
{
	spi = spi;
}

static void spi_unlock(const sfud_spi *spi)
{
	spi = spi;
}

/* about 100 microsecond delay */
static void retry_delay_100us(void)
{
	syscnt_udelay(100);
}

sfud_err sfud_spi_port_init(sfud_flash *flash)
{

	sfud_err result = SFUD_SUCCESS;

	switch (flash->index) {
		case SFUD_GD25Q40E_DEVICE_INDEX:
		case SFUD_GT25Q40C_DEVICE_INDEX:
		{
			flash->spi.wr = spi_write_read;
			flash->spi.qspi_wr = qspi_write_read;
			flash->spi.lock = spi_lock;
			flash->spi.unlock = spi_unlock;
			flash->spi.user_data = &flash_cs;
			flash->retry.delay = retry_delay_100us;
			flash->retry.times = 60 * 10000;
			break;
		}
	}

	return result;
}

/**
 * This function is print debug info.
 *
 * @param file the file which has call this function
 * @param line the line number which has call this function
 * @param format output format
 * @param ... args
 */
void sfud_log_debug(const char *func, const long line, const char *format, ...)
{
	va_list args;

	/* args point to the first variable parameter */
	printf("[SFUD](%s:%ld) ", func, line);
	/* must use vprintf to print */
	va_start(args, format);
	vprintf(format, args);
	va_end(args);
	printf("\r\n");
}

/**
 * This function is print routine info.
 *
 * @param format output format
 * @param ... args
 */
void sfud_log_info(const char *format, ...)
{
	va_list args;

	/* args point to the first variable parameter */
	printf("[SFUD]");
	/* must use vprintf to print */
	va_start(args, format);
	vprintf(format, args);
	va_end(args);
	printf("\r\n");
}
